﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Dynamic;
using System.Text.Json;
using System.Text.Json.Serialization;

using zijian666.Converts.Abstractions;
using zijian666.Converts.Core;

namespace zijian666.Converts.Json;

/// <summary>
/// <seealso cref="JsonElement"/> 翻译器
/// </summary>
public class JsonElementTranslator : JsonConverter<object>, ITranslator
{

    /// <inheritdoc />
    public bool CanTranslate(Type type) => type == typeof(JsonElement);
    /// <inheritdoc />
    public object? Translate(IConvertContext context, object input)
    {
        var conv = context.Settings.GetConvertor<DynamicObject>(context);
        return Translate(context, conv, input);
    }
    /// <summary>
    /// 翻译值
    /// </summary>
    /// <param name="context">转换上下文</param>
    /// <param name="convertor">转换器</param>
    /// <param name="input">输入值</param>
    /// <returns></returns>
    public object? Translate(IConvertContext context, IConvertor<DynamicObject>? convertor, object input)
    {
        var element = (JsonElement)input;
        switch (element.ValueKind)
        {

            case JsonValueKind.Array:
                var list = new ArrayList();
                foreach (var item in element.EnumerateArray())
                {
                    _ = list.Add(Translate(context, convertor, item));
                }
                return Dynamic(context, convertor, list.ToArray());
            case JsonValueKind.Object:
                var expando = new Dictionary<string, object?>();
                foreach (var item in element.EnumerateObject())
                {
                    expando.Add(item.Name, Translate(context, convertor, item.Value));
                }
                return Dynamic(context, convertor, expando);
            case JsonValueKind.String:
                return Dynamic(context, convertor, element.GetString());
            case JsonValueKind.Number:
                return Dynamic(context, convertor, element.GetDecimal());
            case JsonValueKind.True:
                return Dynamic(context, convertor, true);
            case JsonValueKind.False:
                return Dynamic(context, convertor, false);
            case JsonValueKind.Null:
            case JsonValueKind.Undefined:
                return Dynamic(context, convertor, DBNull.Value);
            default:
                return Dynamic(context, convertor, null);
        }
    }

    /// <summary>
    /// 将 <paramref name="value"/> 转为动态类型
    /// </summary>
    public object? Dynamic(IConvertContext context, IConvertor<DynamicObject>? convertor, object? value)
    {
        if (convertor is not null)
        {
            var result = convertor.Convert(context, value);
            if (result.Success)
            {
                return result.Value;
            }
        }
        return value;
    }

    /// <inheritdoc />
    public override object Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        var element = JsonSerializer.Deserialize<JsonElement>(ref reader, options);
#pragma warning disable CS8603 // 可能返回 null 引用。
        return Translate(ConvertContext.Current ?? new ConvertContext(), element);
#pragma warning restore CS8603 // 可能返回 null 引用。
    }

    /// <inheritdoc />
    public override void Write(Utf8JsonWriter writer, object value, JsonSerializerOptions options) => throw new NotImplementedException();
}
